package com.fjeld.middleware.jaxb.util;

import com.fjeld.middleware.constants.PropertiesManager;
import com.fjeld.middleware.jaxb.ObjectFactory;
import com.fjeld.middleware.jaxb.V1Message;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by IntelliJ IDEA.
 * User: fjeld
 * Date: 03/01/2012
 * Time: 07:53
 * <p/>
 * Holds a pool of V1Messages and replenishes these when dropping below a configurable threshold..
 */
public class V1MessagePool extends Thread
{
    private static final Logger LOGGER = Logger.getLogger(V1MessagePool.class);

    private List<V1Message> pool;
    private int threshold, poolSize;
    private boolean isReplenishing = false;
    private final ReentrantLock lock = new ReentrantLock();

    public V1MessagePool()
    {
        String thresholdString = PropertiesManager.getProperties().getProperty("V1MessagePool.Threshold", "3500");
        threshold = Integer.parseInt(thresholdString);
        LOGGER.info("Threshold: " + threshold);

        String poolSizeString = PropertiesManager.getProperties().getProperty("V1MessagePool.PoolSize", "4000");
        poolSize = Integer.parseInt(poolSizeString);
        LOGGER.info("Reserved pool size: " + poolSize);

        pool = new ArrayList<V1Message>(poolSize);
        LOGGER.info("Current pool size: " + pool.size());

        while (pool.size() < poolSize)
        {
            pool.add(ObjectFactory.OBJECT_FACTORY.createV1Message());
        }

        this.setPriority(Thread.MAX_PRIORITY);
    }

    public V1Message getV1Message()
    {
        if (pool.size() == 0)
        {
            throw new RuntimeException("Poolsize is zero! Can not return V1Message!");
        }

        V1Message v1Message = pool.remove(0);

        if (pool.size() <= threshold)
        {
            lock.lock();
            try
            {
                if (!isReplenishing)
                {
                    isReplenishing = true;
                    this.start();
                }
            } finally
            {
                lock.unlock();
            }
        }

        return v1Message;
    }

    public void run()
    {
        int itemsToAdd = poolSize - pool.size();
        LOGGER.info("Replenishing pool with " + itemsToAdd + " V1Message objects.");
        for (int i = 0; i < itemsToAdd; i++)
        {
            pool.add(ObjectFactory.OBJECT_FACTORY.createV1Message());
        }
        isReplenishing = false;
        LOGGER.info("Finished replenishing pool.");
    }
}
